package com.chess.chessplay.pojo;

import java.io.*;
import java.nio.charset.Charset;

public class Eval {
    //    文件名
    private String classname;
    private boolean isCompiler = false;
    //    扩展名
    private final static String fx = ".java";
    //    编码格式，由于是在windows下，故dos窗口为gbk格式
    private final Charset charset = Charset.forName("GBK");
    //    将要被执行的代码
    private final StringBuilder code = new StringBuilder();
    //    设置java文件所在的目录
    private String PATH = "E:\\java\\Test\\";

    public Eval(String code) {
        init(code);
    }

    public Eval(String path, String name) {
        PATH = path;
        int doc = name.lastIndexOf(".");
        if (name.substring(doc).equals(".java")) {
            this.classname = name.substring(0, doc);
        } else {
            init(getCode(name));
        }
    }


    private void init(String code) {
        if (code.contains("public class ")) {
            this.code.append(code);
            initClassname();
        } else {
            initCode();
            this.code.append(code);
            endCode();
        }
        writeFile();
    }

    public void compiler() {
        try {
            Process exec = Runtime.getRuntime().exec("javac " + classname + fx, null, new File(PATH));
            StringBuilder compilerInfo = new StringBuilder();
            try (BufferedReader bf = new BufferedReader(
                    new InputStreamReader(exec.getErrorStream(), charset))) {
                String line;
                while ((line = bf.readLine()) != null) {
                    compilerInfo.append(line);
                    compilerInfo.append("\n");
                }
                if (compilerInfo.length() == 0) {
                    isCompiler = true;
                    System.out.println(classname + fx + " 编译成功！");
                } else {
                    System.out.println("编译失败");
                    System.out.println(compilerInfo.toString());
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void run() {
        if (!isCompiler) {
            System.out.println("编译失败，无法运行！");
            System.exit(0);
        }
        try {
            /**
             * exec()，有三个参数，分别为
             * command: 系统命令，如cd、ls、cat等等
             * envp：一个string[]，每一个参数代表环境变量，若当前继承了进程的系统环境变量，则为null
             * path：当前进程的工作目录（特别重要，比如在执行jar包时，就应该在jar包下的当前目录才可以执行）
             */
            Process exec = Runtime.getRuntime().exec("java " + classname, null, new File(PATH));
            StringBuilder runInfo = new StringBuilder();
            try (BufferedReader bf = new BufferedReader(
                    new InputStreamReader(exec.getInputStream(), charset))) {
                String line;
                while ((line = bf.readLine()) != null) {
                    runInfo.append(line);
                    runInfo.append("\n");
                }
                System.out.println(classname + " 运行成功！");
//                System.out.println(runInfo.toString());
                System.out.println(runInfo);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private String getCode(String name) {
        StringBuilder sb = new StringBuilder();
        try (BufferedReader bf =
                     new BufferedReader(
                             new InputStreamReader(new FileInputStream(PATH + name)));) {
            String line;
            while ((line = bf.readLine()) != null) {
                sb.append(line);
                sb.append("\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

    private void writeFile() {
        try (PrintStream ps = new PrintStream(PATH + classname + fx);) {//生成。java文件
            ps.println(code.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void initClassname() {
        String s = "public class ";
        int classnameStart = code.indexOf(s) + s.length();
        int classnameEnd = code.indexOf(" ", classnameStart);
        classname = code.substring(classnameStart, classnameEnd);
    }

    private void initCode() {
        code.append("public class Test {");
        code.append("    public static void main(String [] args){");
        classname = "Test";
    }

    private void endCode() {
        code.append("}");
        code.append("}");
    }
}
